/*-
 * PDUEntry.java
 *
 * Copyright (c) 2007, Stein Gunnar Bakkeby
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Stein Gunnar Bakkeby nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.googlecode.attention;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;



/**
 * This represents the PDU entry as retrieved via AT commands.
 *
 * @author Stein Gunnar Bakkeby
 */
public class PDUEntry implements SMSEntry {
  
  private static final long serialVersionUID = -6949986575058970694L;
  
  /* Field values */
  private int memoryIndex = -1;
  private Status status = Status.UNKNOWN;
  private String alpha = null;
  private int length = 0;
  private String pdu = null;
  
  /**
   * This will return the memory index of
   * the PDUEntry in the preferred storage.
   * 
   * @return The index
   */
  public int getMemoryIndex() {
    return memoryIndex;
  }
  
  /**
   * This will set the memory index of this PDUEntry.
   * 
   * @param memoryIndex The index
   */
  public void setMemoryIndex(int memoryIndex) {
    this.memoryIndex = memoryIndex;
  }

  /**
   * This will return the status of the PDUEntry.
   * 
   * @return The status
   */
  public Status getStatus() {
    return status;
  }

  /**
   * This will set the status of the PDUEntry.
   * 
   * @param status The status 
   */
  public void setStatus(final Status status) {
    this.status = status;
  }

  /**
   * String type alphanumeric representation of <da> or <oa>
   * corresponding to the entry found in phonebook; implementation
   * of this feature is manufacturer specific.
   * 
   * @return Implementation specific alphanumeric DA or OA 
   */
  public String getAlpha() {
    return alpha;
  }

  /**
   * This will set the alpha.
   * 
   * @param alpha The alpha
   * @see #getAlpha()
   */
  public void setAlpha(final String alpha) {
    this.alpha = alpha;
  }

  /**
   * This will return the length of the PDUEntry.
   * 
   * @return The length
   */
  public int getLength() {
    return length;
  }

  /**
   * This will set the length of the PDUEntry.
   * 
   * @param length The length
   */
  public void setLength(final int length) {
    this.length = length;
  }

  /**
   * This will return the PDUEntry.
   * 
   * @return The PDUEntry
   */
  public String getPDU() {
    return pdu;
  }

  /**
   * This will set the PDUEntry.
   * 
   * @param pdu The PDUEntry
   */
  public void setPDU(final String pdu) {
    this.pdu = pdu;
  }
  
  public String toString() {
    final StringBuilder sb = new StringBuilder(length + 20);
    sb.append("+CMGL: ");
    sb.append(memoryIndex);
    sb.append(',');
    if (status != null) sb.append(status.getValue());
    sb.append(',');
    if (alpha != null) sb.append(alpha);    
    sb.append(',');
    sb.append(length);
    sb.append("\r\n");
    sb.append(pdu);    
//    
//    if (memoryIndex != -1) {
//      sb.append("[Mem:");
//      sb.append(memoryIndex);
//      sb.append(']');
//    }
//    if (status != null) {
//      sb.append("[ST:");
//      sb.append(status.getValue());
//      sb.append(']');
//    }
//    if (alpha != null && !alpha.equals("")) {
//      sb.append("[Alpha:");
//      sb.append(alpha);
//      sb.append(']');
//    }
//    sb.append("[Length:");
//    sb.append(length);
//    sb.append("]\n");
//    sb.append(pdu);
//    
    return sb.toString();
  }
  
  /**
   * Parses a string of PDU entries and converts them into SMSEntry objects.
   * <BR><BR>
   * Regex for AT+CMGL=[0-4] in PDU mode.<BR>
   * <B>(?:\+CMGL:|\^SMGL:) (\d+),(\d),([+A-Za-z0-9]+)?,(\d+)\r?\n([0-9A-Fa-f]+)
   * </B><BR><BR>
   * <B>Group(0)</B> =<BR> 
   * +CMGL: 1,1,,152\r\n0791449785788908040C914497019200590000707020
   * 9053354098C8329A053AA7D76B5078BDAECBC37490F92D17A7416537489C668
   * 3DE67D0FC019A3F401D50990E9A3FDC6ED0515E0ED34142799A1E4EBB41EBB0
   * 9C0E62A7CFE73208FE0089C3EB79995EA6B340EF3368FE00D1CBEE35BD0CEA8
   * 0C274D0FCE17683D06139C89E06BDCFF3070BD42EBB41F307C81E069141F687
   * 7C0E12A7D92E970B544693CF<BR>
   * <B>Group(1)</B> = 1         <--- Memory Index<BR>
   * <B>Group(2)</B> = 1         <--- Status (1 == received read)<BR>
   * <B>Group(3)</B> = null      <--- Alpha (string repr. of number, can be null)<BR>
   * <B>Group(4)</B> = 152       <--- Length of PDU<BR>
   * <B>Group(5)</B> = 0791449785788908040C91449701920059000070702090533540
   * 98C8329A053AA7D76B5078BDAECBC37490F92D17A7416537489C6683DE67D0F
   * C019A3F401D50990E9A3FDC6ED0515E0ED34142799A1E4EBB41EBB09C0E62A7
   * CFE73208FE0089C3EB79995EA6B340EF3368FE00D1CBEE35BD0CEA80C274D0F
   * CE17683D06139C89E06BDCFF3070BD42EBB41F307C81E069141F6877C0E12A7
   * D92E970B544693CF<BR>
   * 
   * @param entries
   * @return
   */
  public static SMSEntry[] parsePDUEntries(final String entries) {
    final Pattern pattern = Pattern.compile(
        "(?:\\+CMGL:|\\^SMGL:) (\\d+),(\\d),([+A-Za-z0-9]+)?,(\\d+)\\r?\\n([0-9A-Fa-f]+)");
    final Matcher matcher = pattern.matcher(entries);
    final ArrayList<SMSEntry> pdus = new ArrayList<SMSEntry>();
    while (matcher.find()) {
      final PDUEntry pdu = new PDUEntry();
      pdu.setMemoryIndex(Integer.parseInt(matcher.group(1)));
      pdu.setStatus(Status.getStatus(matcher.group(2).charAt(0)));
      pdu.setAlpha(matcher.group(3));
      pdu.setLength(Integer.parseInt(matcher.group(4)));
      pdu.setPDU(matcher.group(5));
      pdus.add(pdu);
    }
    return pdus.toArray(new SMSEntry[pdus.size()]);
  }
  
  public boolean equals(final Object another) {
    if (another instanceof SMSEntry) {
      final SMSEntry entry = (SMSEntry) another;
      final String alpha = entry.getAlpha();
      final String thisAlpha = this.getAlpha();
      if (alpha == null && thisAlpha == null
          || (alpha != null && alpha.equals(thisAlpha))) {
        if (entry.getLength() == this.getLength()) {
          if (entry.getMemoryIndex() == this.getMemoryIndex()) {
            if (entry.getPDU().equals(this.getPDU())) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }
}